home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / visulztn / saoimage / saoimage.lha / grphgrab.c < prev    next >
C/C++ Source or Header  |  1990-04-20  |  8KB  |  291 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    grphgrab.c (Color Graph Grab Vertex)
  6.  * Purpose:    Get or drop a color graph vertex as per a mouse button event
  7.  * Subroutine:    grab_cgraph_vertex()        returns: void
  8.  * Subroutine:    drop_cgraph_vertex()        returns: int
  9.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  10.  *        You may do anything you like with this file except remove
  11.  *        this copyright.  The Smithsonian Astrophysical Observatory
  12.  *        makes no representations about the suitability of this
  13.  *        software for any purpose.  It is provided "as is" without
  14.  *        express or implied warranty.
  15.  * Modified:    {0} Michael VanHilst    initial version         11 June 1989
  16.  *        {n} <who> -- <does what> -- <when>
  17.  */
  18.  
  19. #include <X11/Xlib.h>        /* X window stuff */
  20. #include <X11/Xutil.h>        /* X window manager stuff */
  21. #include "hfiles/color.h"    /* color structs */
  22. #include "hfiles/cgraph.h"
  23. #include "hfiles/define.h"    /* YES, NO, MIN, MAX and more */
  24.  
  25. extern struct cgraphRec cgraph;
  26.  
  27. #define GRAB_RANGE 8    /* radius in screen pixels within which to grab mark */
  28.  
  29. /*
  30.  * Subroutine:    grab_cgraph_vertex
  31.  * Purpose:    When a mouse button is pressed, assign a vertex to that button
  32.  */
  33. void get_cgraph_vertex ( event )
  34.      XEvent *event;
  35. {
  36.   static void get_color_vertex();
  37.  
  38.   switch( event->xbutton.button ) {
  39.   case Button1:
  40.     /* note: Sun compiler sometimes muffs these pointers */
  41.     get_color_vertex(event->xbutton.x, event->xbutton.y, &(cgraph.red));
  42.     cgraph.red.active = 1;
  43.     break;
  44.   case Button2:
  45.     get_color_vertex(event->xbutton.x, event->xbutton.y, &(cgraph.green));
  46.     cgraph.green.active = 1;
  47.     break;
  48.   case Button3:
  49.     get_color_vertex(event->xbutton.x, event->xbutton.y, &(cgraph.blue));
  50.     cgraph.blue.active = 1;
  51.     break;
  52.   }
  53. }
  54.  
  55. /*
  56.  * Subroutine:    drop_cgraph_vertex
  57.  * Purpose:    Delete a vertex if one is under the mouse pointer for drop
  58.  *        event
  59.  * Returns:    1 if a vertex was dropped, else 0
  60.  */
  61. int drop_cgraph_vertex ( event )
  62.      XEvent *event;
  63. {
  64.   static int drop_color_vertex();
  65.  
  66.   switch( event->xbutton.button ) {
  67.   case Button1:
  68.     return( drop_color_vertex(&cgraph.red,
  69.                   event->xbutton.x, event->xbutton.y) );
  70.   case Button2:
  71.     return( drop_color_vertex(&cgraph.green,
  72.                   event->xbutton.x, event->xbutton.y) );
  73.   case Button3:
  74.     return( drop_color_vertex(&cgraph.blue,
  75.                   event->xbutton.x, event->xbutton.y) );
  76.   default:
  77.     return( 0 );
  78.   }
  79. }
  80.  
  81. /*
  82.  * Subroutine:    get_color_vertex
  83.  * Purpose:    Handle grab vertex event for single color 
  84.  * Method:    Grab old vertex or make new vertex - under mouse pointer
  85.  */
  86. static void get_color_vertex ( x, y, col )
  87.      int x, y;
  88.      struct colgRec *col;
  89. {
  90.   void install_draw_queue_end();
  91.   static int grab_old_color_vertex();
  92.   static void install_new_color_vertex();
  93.  
  94.   /* clip against limits */
  95.   if( x < cgraph.graph.xzero )
  96.     x = cgraph.graph.xzero;
  97.   else if( x > cgraph.graph.xmax )
  98.     x = cgraph.graph.xmax;
  99.   if( y < cgraph.graph.yzero )
  100.     y = cgraph.graph.yzero;
  101.   else if( y > cgraph.graph.ymax )
  102.     y = cgraph.graph.ymax;
  103.   if( grab_old_color_vertex(x, y, col) == 0 )
  104.     install_new_color_vertex(x, y, col);
  105.   install_draw_queue_end(col);
  106. }
  107.  
  108. /*
  109.  * Subroutine:    grab_old_color_vertex
  110.  * Purpose:    Check to see if position is close to an existing hash mark.
  111.  *        If so, set active markers.
  112.  * Returns:    1 if a vertex was grabbed, else 0
  113.  */
  114. static int grab_old_color_vertex ( x, y, col )
  115.      int x, y;
  116.      struct colgRec *col;
  117. {
  118.   int i, match;
  119.   XRectangle *hash;
  120.  
  121.   hash = col->hash;
  122.   if( col->hash_cnt <= 0 )
  123.     return( 0 );
  124.   /* hash mark positions are upper left corner of hash box */
  125.   x -= HASH_RAY;
  126.   y -= HASH_RAY;
  127.   match = -1;
  128.   /* loop to look for close vertices */
  129.   for( i = 0; i < col->hash_cnt; i++) {
  130.     if( (abs(hash[i].x - x) < GRAB_RANGE) &&
  131.     (abs(hash[i].y - y) < GRAB_RANGE) ) {
  132.       if( match < 0 ) {
  133.     match = i;
  134.       } else if( (SQR(hash[match].x - x) + SQR(hash[match].y - y)) >
  135.          (SQR(hash[i].x - x) + SQR(hash[i].y - y)) ) {
  136.     /* if not only point within range, compare */
  137.     match = i;
  138.       }
  139.     }
  140.   }
  141.   if( match >= 0 ) {
  142.     col->active_hash = match;
  143.     /* hash marks may be a contiguous subset of vertexes, use offset */
  144.     col->active_vertex = match + col->hash_0;
  145.     return( 1 );
  146.   } else
  147.     return( 0 );
  148. }
  149.  
  150. /*
  151.  * Subroutine:    install_new_color_vertex
  152.  * Purpose:    Given hash position, install a new vertex, and make active
  153.  */
  154. static void install_new_color_vertex ( x, y, col )
  155.      int x, y;            /* i: position of ULcorner of new hash mark */
  156.      struct colgRec *col;    /* i: color info structure for one color */
  157. {
  158.   double intensity, cell_level;
  159.   int match;
  160.   int select_best_hash_position();
  161.   static void add_color_vertex(), add_color_vertex_hash();
  162.  
  163.   col->active_hash = select_best_hash_position(x, y, col->hash, col->hash_cnt,
  164.                            &match, cgraph.vertical);
  165.   col->active_vertex = col->active_hash + col->hash_0;
  166.   if( match >= 0 ) {
  167.     /* new vertex must have same level as an existing one */
  168.     cell_level = col->table->cell_level[match + col->hash_0];
  169.   } else {
  170.     if( cgraph.vertical )
  171.       cell_level = (cgraph.hash.Ymax - (double)(y - HASH_RAY)) /
  172.     cgraph.hash.Yheight;
  173.     else
  174.       cell_level = ((double)(x - HASH_RAY) - cgraph.hash.Xzero) /
  175.     cgraph.hash.Xwidth;
  176.     if( cell_level > 1.0 )
  177.       cell_level = 1.0;
  178.     else if( cell_level < 0.0 )
  179.       cell_level = 0.0;
  180.   }
  181.   if( cgraph.vertical )
  182.     intensity = ((double)(x - HASH_RAY) - cgraph.hash.Xzero) /
  183.       cgraph.hash.Xwidth;
  184.   else
  185.     intensity = (cgraph.hash.Ymax - (double)(y - HASH_RAY)) /
  186.       cgraph.hash.Yheight;
  187.   if( intensity > 1.0 )
  188.     intensity = 1.0;
  189.   else if( intensity < 0.0 )
  190.     intensity = 0.0;
  191.   add_color_vertex(col->table, col->active_vertex, cell_level, intensity);
  192.   add_color_vertex_hash(col, col->active_hash, x, y);
  193.   col->unset = 1;
  194. }
  195.  
  196. /*
  197.  * Subroutine:    add_color_vertex
  198.  * Purpose:    Install new vertex in a color subtableRec.
  199.  */
  200. static void add_color_vertex ( table, index, new_cell_level, new_intensity )
  201.      struct subtableRec *table;    /* i/o: table structure for one color */
  202.      int index;            /* i: index of new vertex */
  203.      double new_cell_level;    /* i: cell_level and intensity of new vertex */
  204.      double new_intensity;
  205. {
  206.   register int i, j;
  207.   int count = table->vertex_cnt;
  208.   double *cell_level = table->cell_level;
  209.   double *base_level = table->base_level;
  210.   double *intensity = table->intensity;
  211.  
  212.   /* make room for the new entry */
  213.   for( i = count, j=i-1; i > index; i=j, j-- ) {
  214.     cell_level[i] = cell_level[j];
  215.     base_level[i] = base_level[j];
  216.     intensity[i] = intensity[j];
  217.   }
  218.   /* install the new entry */
  219.   cell_level[i] = new_cell_level;
  220.   base_level[i] = (new_cell_level - table->bias) / table->contrast;
  221.   intensity[i] = new_intensity;
  222.   ++(table->vertex_cnt);
  223. }
  224.  
  225. /*
  226.  * Subroutine:    add_color_vertex_hash
  227.  * Purpose:    Add a new hash mark
  228.  */
  229. static void add_color_vertex_hash ( col, index, x, y )
  230.      struct colgRec *col;
  231.      int index;
  232.      int x, y;
  233. {
  234.   register int i, j;
  235.   XRectangle *hash;
  236.   int hash_cnt;
  237.  
  238.   hash_cnt = col->hash_cnt;
  239.   hash = col->hash;
  240.   for( i = hash_cnt, j = i - 1; i > index; i = j, j-- ) {
  241.     hash[i].x = hash[j].x;
  242.     hash[i].y = hash[j].y;
  243.   }
  244.   hash[i].x = x - HASH_RAY;
  245.   hash[i].y = y - HASH_RAY;
  246.   ++(col->hash_cnt);
  247. }
  248.  
  249. /*
  250.  * Subroutine:    drop_color_vertex
  251.  * Purpose:    Delete a color table vertex if one is under the mouse position
  252.  * Returns:    1 if vertex was dropped, else 0
  253.  */
  254. static int drop_color_vertex ( col, x, y )
  255.      struct colgRec *col;
  256.      int x, y;
  257. {
  258.   static int grab_old_color_vertex();
  259.  
  260.   /* hash mark positions are upper left corner of hash box */
  261.   x -= HASH_RAY;
  262.   y -= HASH_RAY;
  263.   if( grab_old_color_vertex(x, y, col)  ) {
  264.     register int i, j;
  265.     {
  266.       int count = col->table->vertex_cnt;
  267.       double *cell_level = col->table->cell_level;
  268.       double *base_level = col->table->base_level;
  269.       double *intensity = col->table->intensity;
  270.       for( i = col->active_vertex, j=i+1; j < count; i=j, j++ ) {
  271.     cell_level[i] = cell_level[j];
  272.     base_level[i] = base_level[j];
  273.     intensity[i] = intensity[j];
  274.       }
  275.       --(col->table->vertex_cnt);
  276.     }
  277.     {
  278.       int count = col->hash_cnt;
  279.       XRectangle *hash = col->hash;
  280.       for( i = col->active_hash, j=i+1; j < count; i=j, j++ ) {
  281.     hash[i].x = hash[j].x;
  282.     hash[i].y = hash[j].y;
  283.       }
  284.       --(col->hash_cnt);
  285.     }
  286.     col->unset = 1;
  287.     return( 1 );
  288.   } else
  289.     return( 0 );
  290. }
  291.